# -*- coding:utf-8 -*-
"""
Created on 2009-10-22

@author: summit
"""

import math

from enthought.traits import api as traits
from enthought.traits.ui import api as traitsui
from enthought.tvtk.api import tvtk
from enthought.tvtk import vtk_module as vtk
from enthought.tvtk import tvtk_base
from enthought.tvtk.tvtk_base_handler import TVTKBaseHandler
from enthought.tvtk import messenger
from enthought.tvtk.tvtk_base import deref_vtk
from enthought.tvtk import array_handler
from enthought.tvtk.array_handler import deref_array
from tvtk_classes.tvtk_helper import wrap_vtk
from jolly.visual.vtkPythonViewImage2D import *
from jolly.visual.vtkPythonViewImageCollection import *
from jolly.datamanagement.vtkPythonMetaImageData import *
from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
import wx
from enthought.traits.ui.wx.editor import Editor
from enthought.traits.ui.basic_editor_factory import BasicEditorFactory

#class _wxVTKEditor(Editor):
#    scrollable = True
#    
#    def init(self, parent):
#        self.control = self._create_wxVTK(parent)
#        self.set_tooltip()
#        
#    def update_editor(self):
#        pass
#    
#    def _create_wxVTK(self, parent):
#        
#        panel = wx.Panel(parent, -1, style=wx.CLIP_CHILDREN)
#        sizer = wx.BoxSizer(wx.VERTICAL)
#        panel.SetSizer(sizer)
#        
#        # create and bind wxVTKRenderWindowInteractor to view 
#        self.object.wx_interactor = window = wxVTKRenderWindowInteractor(panel, -1)
#        self.object.render_window = tvtk.to_tvtk(window.GetRenderWindow())
#        
#        sizer.Add(window, 0, wx.EXPAND)
#        self.value.SetMinSize((400,400))
#        
#        return panel
#
#class wxVTKEditor(BasicEditorFactory):
#    klass = _wxVTKEditor
# 
#def make_wx_interactor(parent, editor):
#    import wx
#    panel = wx.Panel(parent, -1, style=wx.CLIP_CHILDREN)
#    sizer = wx.BoxSizer(wx.VERTICAL)
#    panel.SetSizer(sizer)
#    
#    # create and bind wxVTKRenderWindowInteractor to view 
#    editor.object.wx_interactor = window = wxVTKRenderWindowInteractor(panel, -1)
#    editor.object.render_window = tvtk.to_tvtk(window.GetRenderWindow())
#    
#    sizer.Add(window, 0, wx.EXPAND)
#    
#    
#    return panel

class PythonViewImage2D(tvtk.Object):
    '''
    classdocs
    '''
    
#    wx_interactor = traits.Instance(wxVTKRenderWindowInteractor)
    input_file = traits.File()
    input_dir = traits.Directory()
    colloction = traits.Any()

    def __init__(self, obj=None, update=True, **traits):
        '''
        Constructor
        '''
        tvtk_base.TVTKBase.__init__(self, vtkPythonViewImage2D, obj, update, **traits)
        self._vtk_obj.GlobalWarningDisplayOff()
    
    def set_observer(self, obj):
        self.colloction = obj
    
    def create_control(self, parent):
        self.wx_interactor = wxVTKRenderWindowInteractor(parent, -1)
        self.render_window = tvtk.to_tvtk(self.render_window.GetRenderWindow())
        return self.wx_interactor
        
    
    off_screen_rendering = tvtk_base.false_bool_trait(help=\
        """
        Create a window in memory instead of on the screen. This may not
        be supported for every type of window and on some windows you may
        need to invoke this prior to the first render.
        """
    )
    def _off_screen_rendering_changed(self, old_val, new_val):
        self._do_change(self._vtk_obj.SetOffScreenRendering,
                        self.off_screen_rendering_)

    slice_orientation = traits.Trait('xy',
    tvtk_base.TraitRevPrefixMap({'xz': 1, 'yz': 0, 'xy': 2}), help=\
        """
        Set/get the slice orientation
        """
    )
    def _slice_orientation_changed(self, old_val, new_val):
        self._do_change(self._vtk_obj.SetSliceOrientation,
                        self.slice_orientation_)
        if self.colloction:
            self.colloction.SyncSetViewConvention(self.view_convention_)
            self.colloction.SyncReset()
            self.colloction.SyncRender()
    
    view_convention = traits.Trait('radiological',
    tvtk_base.TraitRevPrefixMap({'neurological': 0, 'radiological': 1}), help=\
        """
        Set/get the slice orientation
        """
    )
    def _view_convention_changed(self, old_val, new_val):
        self._do_change(self._vtk_obj.setViewConvention,
                        self.view_convention_)
        if self.colloction:
            self.colloction.SyncSetViewConvention(self.view_convention_)
            self.colloction.SyncReset()
            self.colloction.SyncRender()

    z_slice = traits.Int(0, enter_set=True, auto_set=False, help=\
        """
        @deprecated Replaced by ImageViewer2::SetSlice() as of VTK 5.0.
        """
    )
    def _z_slice_changed(self, old_val, new_val):
        self._do_change(self._vtk_obj.SetZSlice,
                        self.z_slice)

    slice = traits.Int(0, enter_set=True, auto_set=False, help=\
        """
        Set/Get the current slice to display (depending on the orientation
        this can be in X, Y or Z).
        """
    )
    def _slice_changed(self, old_val, new_val):
        self._do_change(self._vtk_obj.SetSlice,
                        self.slice)

    color_level = traits.Float(127.5, enter_set=True, auto_set=False, help=\
        """
        Set window and level for mapping pixels to colors.
        """
    )
    def _color_level_changed(self, old_val, new_val):
        self._do_change(self._vtk_obj.SetColorLevel,
                        self.color_level)

    def _get_renderer(self):
        return wrap_vtk(self._vtk_obj.GetRenderer())
    def _set_renderer(self, arg):
        old_val = self._get_renderer()
        self._wrap_call(self._vtk_obj.SetRenderer,
                        deref_vtk(arg))
        self.trait_property_changed('renderer', old_val, arg)
    renderer = traits.Property(_get_renderer, _set_renderer, help=\
        """
        Get the internal render window, renderer, image actor, and
        image map instances.
        """
    )

    color_window = traits.Float(255.0, enter_set=True, auto_set=False, help=\
        """
        Set window and level for mapping pixels to colors.
        """
    )
    def _color_window_changed(self, old_val, new_val):
        self._do_change(self._vtk_obj.SetColorWindow,
                        self.color_window)

    def _get_render_window(self):
        return wrap_vtk(self._vtk_obj.GetRenderWindow())
    def _set_render_window(self, arg):
        old_val = self._get_render_window()
        self._wrap_call(self._vtk_obj.SetRenderWindow,
                        deref_vtk(arg))
        self.trait_property_changed('render_window', old_val, arg)
    render_window = traits.Property(_get_render_window, _set_render_window, help=\
        """
        Get the internal render window, renderer, image actor, and
        image map instances.
        """
    )
    
    def _input_file_changed(self, old_val, new_val):
        image = vtkPythonMetaImageData()
        image.Read(new_val)
        self._vtk_obj.SetInput(image.getDataSet())
        self._vtk_obj.SetOrientationMatrix(image.getOrientationMatrix())
        self._vtk_obj.Reset()
        self._vtk_obj.Render()
        if self.colloction:
            self.colloction.SyncSetInput(image.getDataSet())
            self.colloction.InstallCrossAxes()
            self.colloction.SyncSetOrientationMatrix(image.getOrientationMatrix())
            self.colloction.SyncReset()
            self.colloction.SyncRender()
           
    
    def _input_dir_changed(self, old_val, new_val):
        image = vtkPythonMetaImageData()
        image.ReadSeriesFile(new_val)
        self._vtk_obj.SetInput(image.getDataSet())
        self._vtk_obj.SetOrientationMatrix(image.getOrientationMatrix())
        self._vtk_obj.Reset()
        self._vtk_obj.Render()
        if self.colloction:
            self.colloction.SyncSetInput(image.getDataSet())
            self.colloction.InstallCrossAxes()
            self.colloction.SyncSetOrientationMatrix(image.getOrientationMatrix())
            self.colloction.SyncReset()
            self.colloction.SyncRender()
        
    def _get_input(self):
        return wrap_vtk(self._vtk_obj.GetInput())
    def _set_input(self, arg):
        old_val = self._get_input()
        self._wrap_call(self._vtk_obj.SetInput,
                        deref_vtk(arg))
        self.trait_property_changed('input', old_val, arg)
    input = traits.Property(_get_input, _set_input, help=\
        """
        Set/Get the input image to the viewer.
        """
    )

    def _get_image_actor(self):
        return wrap_vtk(self._vtk_obj.GetImageActor())
    image_actor = traits.Property(_get_image_actor, help=\
        """
        Get the internal render window, renderer, image actor, and
        image map instances.
        """
    )

    def _get_interactor_style(self):
        return wrap_vtk(self._vtk_obj.GetInteractorStyle())
    interactor_style = traits.Property(_get_interactor_style, help=\
        """
        Get the internal render window, renderer, image actor, and
        image map instances.
        """
    )

    def _get_slice_max(self):
        return self._vtk_obj.GetSliceMax()
    slice_max = traits.Property(_get_slice_max, help=\
        """
        Return the minimum and maximum slice values (depending on the orientation
        this can be in X, Y or Z).
        """
    )

    def _get_slice_min(self):
        return self._vtk_obj.GetSliceMin()
    slice_min = traits.Property(_get_slice_min, help=\
        """
        Return the minimum and maximum slice values (depending on the orientation
        this can be in X, Y or Z).
        """
    )

    def get_slice_range(self, *args):
        """
        V.get_slice_range((int, int))
        this GetSliceRange range range 
         Return the minimum and maximum slice values (depending on the orientation
         this can be in X, Y or Z).
        """
        ret = self._wrap_call(self._vtk_obj.GetSliceRange, *args)
        return ret

    def _get_whole_z_max(self):
        return self._vtk_obj.GetWholeZMax()
    whole_z_max = traits.Property(_get_whole_z_max, help=\
        """
        @deprecated Replaced by ImageViewer2::GetSliceMax() as of VTK 5.0.
        """
    )
    
    

    def _get_whole_z_min(self):
        return self._vtk_obj.GetWholeZMin()
    whole_z_min = traits.Property(_get_whole_z_min, help=\
        """
        @deprecated Replaced by ImageViewer2::GetSliceMin() as of VTK 5.0.
        """
    )

    def _get_window_level(self):
        return wrap_vtk(self._vtk_obj.GetWindowLevel())
    window_level = traits.Property(_get_window_level, help=\
        """
        Get the internal render window, renderer, image actor, and
        image map instances.
        """
    )

    def _get_window_name(self):
        return self._vtk_obj.GetWindowName()
    window_name = traits.Property(_get_window_name, help=\
        """
        Get the name of rendering window.
        """
    )

    def render(self):
        """
        V.render()
        
         Render the resulting image.
        """
        ret = self._vtk_obj.Render()
        return ret
    

    def set_display_id(self, *args):
        """
        V.set_display_id(string)
        
         These are here when using a Tk window.
        """
        ret = self._wrap_call(self._vtk_obj.SetDisplayId, *args)
        return ret

    def set_input_connection(self, *args):
        """
        V.set_input_connection(AlgorithmOutput)
        
         Set/Get the input image to the viewer.
        """
        my_args = [deref_vtk(x) for x in args]
        ret = self._wrap_call(self._vtk_obj.SetInputConnection, *my_args)
        return ret

    def set_parent_id(self, *args):
        """
        V.set_parent_id(string)
        
         These are here when using a Tk window.
        """
        ret = self._wrap_call(self._vtk_obj.SetParentId, *args)
        return ret
    
    world_coordinates = traits.Array(shape=(3,), value=(0.0, 0.0, 0.0), dtype=float, enter_set=True, auto_set=False, cols=3, help=\
        """
        Set / get the center of the sphere.
        """
    )
        
    def set_position(self, *args):
        """
        V.set_position(int, int)
        V.set_position((int, int))
        this SetPosition a a 
         Set/Get the position in screen coordinates of the rendering window.
        """
        ret = self._wrap_call(self._vtk_obj.SetPosition, *args)
        return ret

    def set_size(self, *args):
        """
        V.set_size(int, int)
        V.set_size((int, int))
        this SetSize a a 
         Set/Get the size of the window in screen coordinates in pixels.
        """
        ret = self._wrap_call(self._vtk_obj.SetSize, *args)
        return ret

    def set_window_id(self, *args):
        """
        V.set_window_id(string)
        
         These are here when using a Tk window.
        """
        ret = self._wrap_call(self._vtk_obj.SetWindowId, *args)
        return ret

    def setup_interactor(self, *args):
        """
        V.setup_interactor(RenderWindowInteractor)
        
         Attach an interactor for the internal render window.
        """
        my_args = [deref_vtk(x) for x in args]
        ret = self._wrap_call(self._vtk_obj.SetupInteractor, *my_args)
        return ret

    def update_display_extent(self):
        """
        V.update_display_extent()
        
         Update the display extent manually so that the proper slice for the
         given orientation is displayed. It will also try to set a
         reasonable camera clipping range.
         This method is called automatically when the Input is changed, but
         most of the time the input of this class is likely to remain the same,
         i.e. connected to the output of a filter, or an image reader. When the
         input of this filter or reader itself is changed, an error message might
         be displayed since the current display extent is probably outside
         the new whole extent. Calling this method will ensure that the display
         extent is reset properly.
        """
        ret = self._vtk_obj.UpdateDisplayExtent()
        return ret
    
    def _get_corner_annotation(self):
        return wrap_vtk(self._vtk_obj.getCornerAnnotation())
    corner_annotation = traits.Property(_get_corner_annotation, None, help=\
        """
        Get the internal corner annotation.
        """
    )
    
    def _get_scalar_bar_actor(self):
        return wrap_vtk(self._vtk_obj.getScalarBarActor())
    scalar_bar_actor = traits.Property(_get_scalar_bar_actor, None, help=\
        """
        Get the internal scalar bar actor.
        """
    )
    
    def _get_orientation_matrix(self):
        return wrap_vtk(self._vtk_obj.getOrientationMatrix())
    def _set_orientation_matrix(self, arg):
        old_val = self._get_orientation_matrix()
        self._wrap_call(self._vtk_obj.getOrientationMatrix,
                        deref_vtk(arg))
        self.trait_property_changed('orientation_matrix', old_val, arg)
    orientation_matrix = traits.Property(_get_orientation_matrix, _set_orientation_matrix, help=\
        """
        Get the internal orientation matrix.
        """
    )
    
    def _get_lookup_table(self):
        return wrap_vtk(self._vtk_obj.getLookupTable())
    def _set_lookup_table(self, arg):
        old_val = self._get_lookup_table()
        self._wrap_call(self._vtk_obj.setLookupTable,
                        deref_vtk(arg))
        self.trait_property_changed('lookup_table', old_val, arg)
    lookup_table = traits.Property(_get_lookup_table, _set_lookup_table, help=\
        """
        Get the internal lookup table.
        """
    )
    
    def _get_dataset_clollection(self):
        return wrap_vtk(self._vtk_obj.getDataSetCollection())
    dataset_clollection = traits.Property(_get_dataset_clollection, None, help=\
        """
        Get the internal dataset clollection.
        """
    )
    
    def _get_prop3d_clollection(self):
        return wrap_vtk(self._vtk_obj.getProp3DCollection())
    prop3d_clollection = traits.Property(_get_prop3d_clollection, None, help=\
        """
        Get the internal dataset clollection.
        """
    )
    
    def _get_text_property(self):
        return wrap_vtk(self._vtk_obj.getTextProperty())
    def _set_text_property(self, arg):
        old_val = self._get_text_property()
        self._wrap_call(self._vtk_obj.setTextProperty,
                        deref_vtk(arg))
        self.trait_property_changed('text_property', old_val, arg)
    text_property = traits.Property(_get_text_property, _set_text_property, help=\
        """
        Get the internal text property.
        """
    )
    show_annotation = tvtk_base.false_bool_trait(help=\
        """
        Turn on/off show annotation. Default is on.
        This must be applied before the first Render.
        """
    )
    def _show_annotation_changed(self, old_val, new_val):
        self._do_change(self._vtk_obj.setShowAnnotations,
                        self.show_annotation_)
    
#    enable_interaction = tvtk_base.false_bool_trait(help=\
#        """
#        Turn on/off interaction. Default is On.
#        This must be applied before the first Render.
#        """
#    )
#    def _enable_interaction_changed(self, old_val, new_val):
#        self._do_change(self._vtk_obj.setEnable,
#                        self.enable_interaction_)
    show_scalar_bar = tvtk_base.false_bool_trait(help=\
        """
        Turn on/off show annotation. Default is on.
        This must be applied before the first Render.
        """
    )
    def _show_scalar_bar_changed(self, old_val, new_val):
        self._do_change(self._vtk_obj.setShowScalarBar,
                        self.show_scalar_bar_)

   
    
    def set_world_coordinates(self, *args):
        ret = self._wrap_call(self._vtk_obj.SetWorldCoordinates, *args)
        return ret
    
    def add_dataset(self, *args):
        ret = self._wrap_call(self._vtk_obj.AddDataSet, *args)
        return ret

    def remove_dataset(self, *args):
        ret = self._wrap_call(self._vtk_obj.RemoveDataSet, *args)
        return ret

    def update(self, *args):
        ret = self._wrap_call(self._vtk_obj.Update, *args)
        return ret
    
   
        

    _updateable_traits_ = \
    (('color_level', 'GetColorLevel'), ('slice', 'GetSlice'),
    ('global_warning_display', 'GetGlobalWarningDisplay'),
    ('slice_orientation', 'GetSliceOrientation'), ('z_slice',
    'GetZSlice'), ('color_window', 'GetColorWindow'), ('debug',
    'GetDebug'), ('reference_count', 'GetReferenceCount'),
    ('off_screen_rendering', 'GetOffScreenRendering'), ('show_annotation', 'getShowAnnotations'),
    ('show_scalar_bar', 'getShowScalarBar'),('view_convention', 'getViewConvention'))
    
    _full_traitnames_list_ = \
    (['debug', 'global_warning_display', 'off_screen_rendering',
    'slice_orientation', 'color_level', 'color_window', 'slice',
    'z_slice'])
    
    full_traits_view = \
    traitsui.View((traitsui.Item("handler._full_traits_list",show_label=False)),
    title='Edit PythonViewImage properties', scrollable=True, resizable=True,
    handler=TVTKBaseHandler,
    buttons=['OK', 'Cancel'])
    
    view = \
    traitsui.View((['off_screen_rendering','show_annotation', 'show_scalar_bar'], ['slice_orientation'],
    ['color_level', 'color_window', 'slice', 'z_slice'],[traitsui.Item(name='render_window', editor=traitsui.InstanceEditor())]
    ,[traitsui.Item(name='renderer', editor=traitsui.InstanceEditor())]),
    title='Edit PythonViewImage properties', scrollable=True, resizable=True,
    handler=TVTKBaseHandler,
    buttons=['OK', 'Cancel'])
    
    traits_view = \
    traitsui.View((traitsui.HGroup(traitsui.spring, "handler.view_type", show_border=True), 
    traitsui.Item("handler.info.object", editor = traitsui.InstanceEditor(view_name="handler.view"), style = "custom", show_label=False)),
    title='Edit PythonViewImage properties', scrollable=True, resizable=True,
    handler=TVTKBaseHandler,
    buttons=['OK', 'Cancel'])

pythonviewimage2d_view = \
    traitsui.View((['off_screen_rendering','show_annotation', 'show_scalar_bar'], ['slice_orientation','view_convention'],
    ['color_level', 'color_window', 'slice', 'z_slice',traitsui.Item(name='input_file', editor=traitsui.FileEditor()),
     traitsui.Item(name='input_dir', editor=traitsui.DirectoryEditor())],[traitsui.Item(name='render_window', editor=traitsui.InstanceEditor())]
    ,[traitsui.Item(name='renderer', editor=traitsui.InstanceEditor())]),
    title='Edit PythonViewImage properties', scrollable=True, resizable=True,
    handler=TVTKBaseHandler,
    kind='panel')
    
if __name__=="__main__":
    x = PythonViewImage2D()
    
    x.configure_traits()

